package cn.sytton.taffe.job.util;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import cn.sytton.taffe.framework.util.BeanUtil;
import cn.sytton.taffe.framework.util.SpringContextUtil;
import cn.sytton.taffe.job.constants.ScheduleConstants;
import cn.sytton.taffe.job.entity.JobEntity;
import cn.sytton.taffe.job.entity.JobLogEntity;
import cn.sytton.taffe.job.mapper.JobLogMapper;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.util.StringUtils;

import java.sql.Timestamp;

/**
 * 抽象quartz调用
 *
 * @author ruoyi
 */
@Slf4j
public abstract class AbstractQuartzJob implements Job {
    /**
     * 线程本地变量, 记录任务执行时间
     */
    private static final ThreadLocal<Timestamp> threadLocal = new ThreadLocal<>();

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobEntity jobEntity = new JobEntity();
        BeanUtil.copyBeanProp(jobEntity, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));
        try {
            before(context, jobEntity);
            doExecute(context, jobEntity);
            after(context, jobEntity, null);
        } catch (Exception e) {
            log.error("任务执行异常  - ：", e);
            after(context, jobEntity, e);
        }
    }

    /**
     * 执行前
     *
     * @param context 工作执行上下文对象
     * @param jobEntity 系统计划任务
     */
    protected void before(JobExecutionContext context, JobEntity jobEntity) {
        threadLocal.set(new Timestamp(new java.util.Date().getTime()));
    }

    /**
     * 执行后
     *
     * @param context 工作执行上下文对象
     * @param jobEntity 系统计划任务
     */
    protected void after(JobExecutionContext context, JobEntity jobEntity, Exception e) {
        Timestamp startTime = threadLocal.get();
        threadLocal.remove();

        final JobLogEntity jobLogEntity = new JobLogEntity();
        jobLogEntity.setJobName(jobEntity.getJobName());
        jobLogEntity.setJobGroup(jobEntity.getJobGroup());
        jobLogEntity.setInvokeTarget(jobEntity.getInvokeTarget());
        jobLogEntity.setStartTime(startTime);
        jobLogEntity.setStopTime(new Timestamp(new java.util.Date().getTime()));
        long runMs = jobLogEntity.getStopTime().getTime() - jobLogEntity.getStartTime().getTime();
        jobLogEntity.setRunningTime(runMs);
        if (e != null) {
            log.error(e.getMessage(), e);
            jobLogEntity.setStatus(0);
            String msg = StringUtils.hasText(e.getMessage()) ? e.getMessage() : ExceptionUtil.getRootCauseMessage(e);
            jobLogEntity.setExceptionMessage(StrUtil.sub(msg,0, 2000));
        } else {
            jobLogEntity.setStatus(1);
        }

        // 写入数据库当中
        SpringContextUtil.getBean(JobLogMapper.class).insert(jobLogEntity);
    }

    /**
     * 执行方法，由子类重载
     *
     * @param context 工作执行上下文对象
     * @param jobEntity 系统计划任务
     * @throws Exception 执行过程中的异常
     */
    protected abstract void doExecute(JobExecutionContext context, JobEntity jobEntity) throws Exception;
}
